﻿using Cofe.Core.Filter;
using Cofe.Core.Utils;
using Cofe.IO;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Cofe.Core
{
    public static class IDirectoryInfoExtension
    {
        #region GetSubContents

        /// Return a list of files in current directory that match the search filterStr and search options.
        /// </summary>
        /// <param name="dirEntry"></param>
        /// <param name="searchPattern"></param>
        /// <param name="searchOption"></param>
        /// <returns></returns>
        public async static Task<IFileInfo[]> GetFilesAsync(this IDirectoryInfo dirEntry, String searchPattern, SearchOption searchOption)
        {
            return (await dirEntry.GetCofeSystemInfosAsync(                
                PathUtils.MaskToEntryFilter(searchPattern,
                new FileTypeEntryFilter(FileTypeEntryFilter.File)
             ),
             new IOptionFilter[] { new SearchOptionOptionFilter(searchOption) }, 
             EntryConstructionFlags.Default, CofeServices.EntryConstructor))
             .Where((e) => e.Is<IFileInfo>())             
             .Select(e => e.As<IFileInfo>()).ToArray();
        }

        /// <summary>
        /// Return a list of files in current directory that match the search filterStr .
        /// </summary>
        /// <param name="dirEntry"></param>
        /// <param name="searchPattern"></param>
        /// <returns></returns>
        public async static Task<IFileInfo[]> GetFilesAsync(this IDirectoryInfo dirEntry, String searchPattern)
        {
            return await dirEntry.GetFilesAsync(searchPattern, SearchOption.TopDirectoryOnly);
        }

        /// <summary>
        /// Return a list of files in current directory.
        /// </summary>
        /// <param name="dirEntry"></param>
        /// <returns></returns>
        public async static Task<IFileInfo[]> GetFilesAsync(this IDirectoryInfo dirEntry)
        {
            return await dirEntry.GetFilesAsync("*");
        }

        /// <summary>


        /// <summary>
        /// Return a list of directories in current directory that match the search filterStr and search options.
        /// </summary>
        /// <param name="dirEntry"></param>
        /// <param name="searchPattern"></param>
        /// <param name="searchOption"></param>
        /// <returns></returns>
        public static async Task<IDirectoryInfo[]> GetDirectoriesAsync(this IDirectoryInfo dirEntry, String searchPattern, SearchOption searchOption)
        {
            return (await dirEntry.GetCofeSystemInfosAsync(                 
                 PathUtils.MaskToEntryFilter(searchPattern,
                 new FileTypeEntryFilter(FileTypeEntryFilter.Folder)
              ),
              new IOptionFilter[] { new SearchOptionOptionFilter(searchOption) }, 
              EntryConstructionFlags.Default, CofeServices.EntryConstructor))
              .Where((e) => e.Is<IFileSystemInfo>())             
              .Select((e) => e.As<IDirectoryInfo>()).ToArray();
        }


        /// <summary>
        /// Return a list of directories in current directory that match the search filterStr.
        /// </summary>
        /// <param name="dirEntry"></param>
        /// <param name="searchPattern"></param>
        /// <returns></returns>
        public static async Task<IDirectoryInfo[]> GetDirectoriesAsync(this IDirectoryInfo dirEntry, String searchPattern)
        {
            return await dirEntry.GetDirectoriesAsync(searchPattern, SearchOption.TopDirectoryOnly);
        }


        /// <summary>
        /// Return a list of directories in current directory.
        /// </summary>
        /// <param name="dirEntry"></param>
        /// <returns></returns>
        public static async Task<IDirectoryInfo[]> GetDirectoriesAsync(this IDirectoryInfo dirEntry)
        {
            return await dirEntry.GetDirectoriesAsync("*");
        }


        /// <summary>
        /// Return a list of entries in current directory that match the search filterStr and search options.
        /// </summary>
        /// <param name="dirEntry"></param>
        /// <param name="searchPattern"></param>
        /// <param name="searchOption"></param>
        /// <returns></returns>
        public static async Task<IFileSystemInfo[]> GetFileSystemInfosAsync(this IDirectoryInfo dirEntry, String searchPattern, SearchOption searchOption)
        {
            return (await dirEntry.GetCofeSystemInfosAsync(             
             PathUtils.MaskToEntryFilter(searchPattern),
                new IOptionFilter[] { new SearchOptionOptionFilter(searchOption) },
                EntryConstructionFlags.Default, CofeServices.EntryConstructor))
             .Where((e) => e.Is<IFileSystemInfo>())
             .Select((e) => e.As<IFileSystemInfo>())
             .ToArray();
        }

        /// <summary>
        /// Return a list of entries in current directory that match the search filterStr.
        /// </summary>
        /// <param name="dirEntry"></param>
        /// <param name="searchPattern"></param>
        /// <returns></returns>
        public static async Task<IFileSystemInfo[]> GetFileSystemInfosAsync(this IDirectoryInfo dirEntry, String searchPattern)
        {
            return await dirEntry.GetFileSystemInfosAsync(searchPattern, SearchOption.TopDirectoryOnly);
        }

        /// <summary>
        /// Return a list of entries in current directory.
        /// </summary>
        /// <param name="dirEntry"></param>
        /// <returns></returns>
        public static async Task<IFileSystemInfo[]> GetFileSystemInfosAsync(this IDirectoryInfo dirEntry)
        {
            return await dirEntry.GetFileSystemInfosAsync("*");
        }

        #endregion

        #region EnumerateSubContents
        /// <summary>
        /// Return a enumerable of files in current directory that match the search filterStr and search options.
        /// </summary>
        /// <param name="dirEntry"></param>
        /// <param name="searchPattern"></param>
        /// <param name="searchOption"></param>
        /// <returns></returns>
        public static IEnumerable<IFileInfo> EnumerateFiles(this IDirectoryInfo dirEntry, string searchPattern, SearchOption searchOption)
        {
            return dirEntry.EnumerateCofeSystemInfos(                 
                 PathUtils.MaskToEntryFilter(searchPattern,
                 new FileTypeEntryFilter(FileTypeEntryFilter.File)
              ),
              new IOptionFilter[] { new SearchOptionOptionFilter(searchOption) }, 
              EntryConstructionFlags.Default, CofeServices.EntryConstructor)
              .Where(e => e.Is<IFileInfo>())
              .Select(f => f.As<IFileInfo>());
        }

        /// <summary>
        /// Return a enumerable of files in current directory that match the search filterStr.
        /// </summary>
        /// <param name="dirEntry"></param>
        /// <param name="searchPattern"></param>
        /// <returns></returns>
        public static IEnumerable<IFileInfo> EnumerateFiles(this IDirectoryInfo dirEntry, String searchPattern)
        {
            return dirEntry.EnumerateFiles(searchPattern, SearchOption.TopDirectoryOnly);
        }

        /// <summary>
        /// Return a enumerable of files in current directory.
        /// </summary>
        /// <param name="dirEntry"></param>
        /// <returns></returns>
        public static IEnumerable<IFileInfo> EnumerateFiles(this IDirectoryInfo dirEntry)
        {
            return dirEntry.EnumerateFiles("*");
        }

        public static IFileInfo GetFile(this IDirectoryInfo dirEntry, string fileName)
        {
            return dirEntry.EnumerateFiles(fileName).FirstOrDefault();
        }

        /// <summary>
        /// Return a enumerable of directories in current directory that match the search filterStr and search options.
        /// </summary>
        /// <param name="dirEntry"></param>
        /// <param name="searchPattern"></param>
        /// <param name="searchOption"></param>
        /// <returns></returns>
        public static IEnumerable<IDirectoryInfo> EnumerateDirectories(this IDirectoryInfo dirEntry, string searchPattern, SearchOption searchOption)
        {
            return dirEntry.EnumerateCofeSystemInfos(                
                PathUtils.MaskToEntryFilter(searchPattern,
                new FileTypeEntryFilter(FileTypeEntryFilter.Folder)
             ),
             new IOptionFilter[] { new SearchOptionOptionFilter(searchOption) }, 
             EntryConstructionFlags.Default, CofeServices.EntryConstructor)
             .Where(e => e.Is<IDirectoryInfo>())
             .Select(f => f.As<IDirectoryInfo>());             
        }

        /// <summary>
        /// Return a enumerable of directories in current directory that match the search filterStr.
        /// </summary>
        /// <param name="dirEntry"></param>
        /// <param name="searchPattern"></param>
        /// <returns></returns>
        public static IEnumerable<IDirectoryInfo> EnumerateDirectories(this IDirectoryInfo dirEntry, String searchPattern)
        {
            return dirEntry.EnumerateDirectories(searchPattern, SearchOption.TopDirectoryOnly);
        }

        /// <summary>
        /// Return a enumerable of directories in current directory.
        /// </summary>
        /// <param name="dirEntry"></param>
        /// <returns></returns>
        public static IEnumerable<IDirectoryInfo> EnumerateDirectories(this IDirectoryInfo dirEntry)
        {
            return dirEntry.EnumerateDirectories("*");
        }

        public static IDirectoryInfo GetDirectory(this IDirectoryInfo dirEntry, string dirName)
        {
            return dirEntry.EnumerateDirectories(dirName).FirstOrDefault();
        }


        /// <summary>
        /// Return a enumerable of entries in current directory that match the search filterStr and search options.
        /// </summary>
        /// <param name="dirEntry"></param>
        /// <param name="searchPattern"></param>
        /// <param name="searchOption"></param>
        /// <returns></returns>
        public static IEnumerable<IFileSystemInfo> EnumerateFileSystemInfos(this IDirectoryInfo dirEntry, string searchPattern, SearchOption searchOption)
        {            
           return  dirEntry.EnumerateCofeSystemInfos(                
                PathUtils.MaskToEntryFilter(searchPattern),
             new IOptionFilter[] { new SearchOptionOptionFilter(searchOption) }, 
             EntryConstructionFlags.Default, CofeServices.EntryConstructor)
             .Where((e) => e.Is<IFileSystemInfo>())
             .Select((e) => e.As<IFileSystemInfo>());            
        }

        /// <summary>
        /// Return a enumerable of entries in current directory that match the search filterStr.
        /// </summary>
        /// <param name="dirEntry"></param>
        /// <param name="searchPattern"></param>
        /// <returns></returns>
        public static IEnumerable<IFileSystemInfo> EnumerateFileSystemInfos(this IDirectoryInfo dirEntry, String searchPattern)
        {
            return dirEntry.EnumerateFileSystemInfos(searchPattern, SearchOption.TopDirectoryOnly);
        }

        /// <summary>
        /// Return a enumerable of entries in current directory.
        /// </summary>
        /// <param name="dirEntry"></param>
        /// <returns></returns>
        public static IEnumerable<IFileSystemInfo> EnumerateFileSystemInfos(this IDirectoryInfo dirEntry)
        {
            return dirEntry.EnumerateFileSystemInfos("*");
        }

        public static IFileSystemInfo GetFileSystemInfo(this IDirectoryInfo dirEntry, string name)
        {
            return dirEntry.EnumerateFileSystemInfos(name).FirstOrDefault();
        }

        #endregion

        #region CreateFile/DirectoryAsync
        

        public static async Task<IFileInfo> CreateFileAsync(this IDirectoryInfo directoryInfo, string name)
        {
            return await directoryInfo.CreateAsync<IFileInfo>("file", name);
        }

        public static async Task<IDirectoryInfo> CreateDirectoryAsync(this IDirectoryInfo directoryInfo, string name)
        {
            return await directoryInfo.CreateAsync<IDirectoryInfo>("directory", name);
        }

        #endregion

    }
}
